<!--
 * @Author: your name
 * @Date: 2022-04-06 15:58:36
 * @LastEditTime: 2022-04-06 17:45:30
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \geyao\geyao\发布-订阅者模式例子220406.html
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>发布--订阅者模式</title>
</head>

<body>
  <script>
    ////定义一所学校(中间件，事件派发中心)
    //主要功能包括校园网(topics)，以及学生订阅消息(subscribe)，老师发布课程(publish)
    let School = {
      type: "hunt",
      topics: Object.create(null),
      //添加订阅的事件，当一个对象订阅事件的时候，分别传入事件名字和回调函数(当订阅事件触发时候执行的操作)
      subscribe: function (topic, fn) {
        //如果派发对象内检索不到这个对象，就说明是一个新事件，新建一个数组对象，然后把该订阅者的回调放进事件对象中
        //topics是一个对象，里面有多个事件对象，事件对象内部是一个数组，包含这个事件的订阅者
        if (!this.topics[topic]) {
          this.topics[topic] = [];
          console.log("添加订阅" + topic + "的学生到Peter老师的订阅对象中");
          this.topics[topic].push(fn);
        }

      },
      // 发布事件，在事件订阅对象中检索这个事件，有就调用该对象中所有回调，否则直接返回
      publish: function (topic, money) {
        if (!this.topics[topic]) return;
        for (let fn of this.topics[topic]) {
          console.log("校园网发布" + topic + "课程");
          fn(money);
        }
      }
    }
    //定义一个师生类
    //包括姓名，身份
    function Student(name, identity) {
      this.name = name;
      this.identity = identity;
      //师生可以在校园网上发布订阅任务  //定义一个订阅函数，这里面调用了任务中心的订阅函数，收集所有订阅者的订阅事件和回调
      this.subscribe = function subscribe(topic, fn) {
        console.log(this.identity + "的" + this.name + "在校园网订阅了" + topic + "的课程");
        School.subscribe(topic, fn);
      };
      //定义一个发布函数，这里面调用了任务中心的发布函数，调用所有订阅者的回调  
      this.publish = function publish(topic, money) {
        console.log(this.identity + "老师" + this.name + "在校园网发布了" + topic + "的课程");
        School.publish(topic, money);
      };


    }
    //案例开始，先定义学生，老师
    let studentMing = new Student("小明", "大一");
    let studentJin = new Student("小金", "大一");
    let studentZhang = new Student("小张", "大一");
    let studentPeter = new Student("Peter", "老师");

    //小明，小金，小张分别订阅了发布课程
    studentMing.subscribe("Peter老师", function (money) {
      console.log("小明表示：" + (money = "美术课" ? "不" : "") + "接取美术课");
    });
    studentJin.subscribe("Peter老师", function (money) {
      console.log("小金表示：接取任何课程");
    });
    studentZhang.subscribe("Peter老师", function (money) {
      console.log("小张表示：" + (money = "前端课" ? "我不上其他课," : "") + "我要上前端课啊");
    });
    //Peter发布了课程，美术课
    studentPeter.publish("Peter老师", "美术课");
  </script>
</body>

</html>